/*
	File:	video/model/Animation.hpp
	Date:	2013-06-01
	Author:	Asteroth
*/


#ifndef __ZEN_MODEL_ANIMATION_HPP__
#define __ZEN_MODEL_ANIMATION_HPP__

#include "../../math.hpp"
#include "AnimationFramer.hpp"

namespace zen {

	namespace video {

		namespace model {


			struct AnimKey {
				glm::u32 time;
				glm::mat4 key;
			};


			class Animation {

			public:

				Animation();
				Animation(const Animation &other);
				~Animation();

				Animation& operator = (const Animation &other);
				
				glm::uint getKeyCount()		const { return keyCount; }
				AnimKey* getKeys()			const { return keys; }
				
				void setType(AnimType type);
				void setSpeed(glm::float32 speed);
				void setPosition(glm::uint position);
				void setStart(glm::uint position);
				void setEnd(glm::uint position);

				glm::uint getFirstPosition();
				glm::uint getLastPosition();

				glm::mat4 computeKey() const;
				glm::mat4 computeKey(glm::uint position) const;
				glm::mat4 computeKey(const AnimationFramer &framer) const;
				glm::mat4 computeKey(glm::uint position, const AnimationFramer &framer) const;

				static glm::mat4 computeKey(glm::uint position, glm::uint keyCount, AnimKey* keys, glm::uint startKeyIndex, glm::uint endKeyIndex);

				bool loadResource(jsl::Node* node);

				
			public:
    
				AnimationFramer framer;
				glm::uint keyCount;
				AnimKey* keys;

				static glm::uint searchKeyByPosition(glm::uint position, glm::uint keyCount, AnimKey* keys, glm::uint start, glm::uint end);
				void refreshStartEndKeyIndexes(AnimationFramer &framer) const;

			};


			inline void Animation::setType(AnimType type) {
				framer.setType(type);
			}
			
			inline void Animation::setSpeed(glm::float32 speed) {
				framer.setSpeed(speed);
			}

			inline void Animation::setPosition(glm::uint position) {
				framer.setPosition(position);
			}

			inline void Animation::setStart(glm::uint position) {
				framer.setStart(position);
				refreshStartEndKeyIndexes(framer);
			}

			inline void Animation::setEnd(glm::uint position) {
				framer.setEnd(position);
				refreshStartEndKeyIndexes(framer);
			}
			
			inline glm::uint Animation::getFirstPosition() {
				keys == nullptr ? 0 : keys[0].time;
			}

			inline glm::uint Animation::getLastPosition() {
				keys == nullptr ? 0 : keys[keyCount - 1].time;
			}

			inline glm::mat4 Animation::computeKey() const {
				return computeKey(framer);
			}

			inline glm::mat4 Animation::computeKey(glm::uint position) const {
				return computeKey(position, keyCount, keys, framer.getStartKey(), framer.getEndKey());
			}

			inline glm::mat4 Animation::computeKey(const AnimationFramer &framer) const {
				return computeKey(framer.getPosition(), framer);
			}

			inline glm::mat4 Animation::computeKey(glm::uint position, const AnimationFramer &framer) const {
				return computeKey(position, keyCount, keys, framer.getStartKey(), framer.getEndKey());
			}

				


		} // namespace model

	} // namespace video

} // namespace zen

#endif // __ZEN_MODEL_ANIMATION_HPP__
